package com.woniuxy.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.core.exception.accountException.AccountException;
import com.woniuxy.core.exception.accountException.AccountExceptionCode;
import com.woniuxy.core.staticCode.UserCode;
import com.woniuxy.core.util.RedisKeyUtil;
import com.woniuxy.core.util.RedisUtil;
import com.woniuxy.core.util.SMSUtil;
import com.woniuxy.user.dao.UserAccount;
import com.woniuxy.user.dao.UserInfo;
import com.woniuxy.user.mapper.UserAccountMapper;
import com.woniuxy.user.mapper.UserInfoMapper;
import com.woniuxy.user.model.dto.UserLoginDto;
import com.woniuxy.user.model.form.AddUserForm;
import com.woniuxy.user.model.form.UserLogin1Form;
import com.woniuxy.user.model.form.UserLoginForm;
import com.woniuxy.user.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 凌玉春
 * @since 2024年01月15日
 */
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Resource
    private SMSUtil smsUtil;

    @Autowired
    private UserAccountMapper userAccountMapper;

    public void register(AddUserForm form) throws Exception {
        System.out.println("这是master分支的内容");
        if (form.getUserInfoTel()==null){
            throw  new AccountException(AccountExceptionCode.NOT_NULL);
        }
        if (form.getUserAccount()==null){
            throw  new AccountException(AccountExceptionCode.NOT_NULL);
        }
        if (form.getUserPass()==null){
            throw  new AccountException(AccountExceptionCode.NOT_NULL);
        }
        if (form.getCode()==null){
            throw  new AccountException(AccountExceptionCode.NOT_NULL);
        }

        QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("user_account",form.getUserAccount());
        UserAccount userAccount1 = userAccountMapper.selectOne(wrapper);
        if (userAccount1!=null){
           throw  new AccountException(AccountExceptionCode.ACCIUNT_USERUSE);
        }

        QueryWrapper<UserAccount> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("user_info_tel",form.getUserInfoTel());
        UserAccount userAccount2 = userAccountMapper.selectOne(wrapper1);
        System.out.println("--------------");
        System.out.println(form.getUserInfoTel());
        System.out.println("--------------");
        if (userAccount2!=null){
            throw new AccountException(AccountExceptionCode.PHONE_USSERUSE);
        }


        //创建锁
        RLock lock1 = redissonClient.getFairLock(RedisKeyUtil.lockPhone(form.getUserInfoTel()));
        RLock lock2 = redissonClient.getFairLock(RedisKeyUtil.lockUserName(form.getUserAccount()));
        RLock Lock = redissonClient.getMultiLock(lock1, lock2);
        String total = redisUtil.get(RedisKeyUtil.erroTotal(form.getUserInfoTel()));
        if (total != null && Integer.parseInt(total) > 5) {
            //删除验证码 和 验证码错误计数器
            redisUtil.del1(RedisKeyUtil.registerCodeKey(form.getUserInfoTel()));
            redisUtil.del1(RedisKeyUtil.erroTotal(form.getUserInfoTel()));
            throw new AccountException(AccountExceptionCode.CODE_MAX);
        }
        //取出实际的验证码
        String code = redisUtil.get(RedisKeyUtil.registerCodeKey(form.getUserInfoTel()));
        ///ada
        String code1 = form.getCode();
        if (code1 == null || code1 == "") {
            throw new AccountException(AccountExceptionCode.CODE_NOT_NULL);
        }
        if (!form.getCode().equals(code)) {
            if (!redisUtil.exists(RedisKeyUtil.erroTotal(form.getUserInfoTel()))) {
                redisUtil.set(RedisKeyUtil.erroTotal(form.getUserInfoTel()), "1", 5 * 60);
            } else {
                redisUtil.incr(RedisKeyUtil.erroTotal(form.getUserInfoTel()));
            }
            throw new AccountException(AccountExceptionCode.VERIFICATION_CODE_ERROR);
        }
        boolean b = Lock.tryLock(20, TimeUnit.SECONDS);
        if (b) {
            try {
                UserAccount userAccount = BeanUtil.toBean(form, UserAccount.class);
                userAccount.setUserState(UserCode.USER_CODE.getCode());
                userAccountMapper.insert(userAccount);
                //得到用户id
                Integer userId = userAccount.getUserId();
                UserInfo userInfo = BeanUtil.toBean(userAccount, UserInfo.class);
                userInfo.setUserAccountId(userId);
                //1表示未进行实名认证
                userInfo.setUserRealNameState(1);
                userInfoMapper.insert(userInfo);
                //删除发送的验证码
                redisUtil.del1(RedisKeyUtil.registerCodeKey(form.getUserInfoTel()));
            } finally {
                Lock.unlock();
            }
        } else {
            throw new AccountException(AccountExceptionCode.SERVER_BUSY);
        }

    }

    @Override
    public void send(String userInfoTel) throws Exception {
        if (redisUtil.exists(RedisKeyUtil.sendRegisterCodeInMinute(userInfoTel))) {
            throw new AccountException(AccountExceptionCode.DONT_ALWAYS_BUSY);
        }
        String total = redisUtil.get(RedisKeyUtil.codeTotalInHour(userInfoTel));
        if (total != null && Integer.parseInt(total) >= 5) {
            throw new AccountException(AccountExceptionCode.TIMEOUT);
        }

        QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("user_info_tel", userInfoTel);
        UserAccount userInfo = userAccountMapper.selectOne(wrapper);
        if (userInfo != null) {
            throw new AccountException(AccountExceptionCode.PHONE_OCCUPY);
        }
        String code = smsUtil.send(userInfoTel);

        redisUtil.set(RedisKeyUtil.registerCodeKey(userInfoTel), code, 5 * 60);
        redisUtil.set(RedisKeyUtil.sendRegisterCodeInMinute(userInfoTel), "0", 60);
        if (!redisUtil.exists(RedisKeyUtil.codeTotalInHour(userInfoTel))) {
            redisUtil.set(RedisKeyUtil.codeTotalInHour(userInfoTel), "1", 60 * 60);
        } else {
            redisUtil.incr(RedisKeyUtil.codeTotalInHour(userInfoTel));
        }
    }

    @Override
    public UserLoginDto login(UserLoginForm uf) {
        if(uf.getUserAccount()==null){
            throw new AccountException(AccountExceptionCode.USERACCOUNT_NOT_NULL);
        }
        if(uf.getUserPass()==null){
            throw new AccountException(AccountExceptionCode.USERPASS_NOT_NULL);
        }
        QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("user_account",uf.getUserAccount());
        wrapper.eq("user_pass",uf.getUserPass());
        UserAccount userAccount = userAccountMapper.selectOne(wrapper);
        if(userAccount==null){
            throw new AccountException(AccountExceptionCode.ERROR_ACCPSS);
        }
        return BeanUtil.toBean(userAccount,UserLoginDto.class);
    }

    @Override
    public UserLoginDto login1(UserLogin1Form uf) throws Exception {
        //创建锁
        RLock lock1 = redissonClient.getFairLock(RedisKeyUtil.lockPhone(uf.getUserInfoTel()));
        RLock Lock = redissonClient.getMultiLock(lock1);
        String total = redisUtil.get(RedisKeyUtil.erroTotal(uf.getUserInfoTel()));
        if (total != null && Integer.parseInt(total) > 5) {
            //删除验证码 和 验证码错误计数器
            redisUtil.del1(RedisKeyUtil.registerCodeKey(uf.getUserInfoTel()));
            redisUtil.del1(RedisKeyUtil.erroTotal(uf.getUserInfoTel()));
            throw new AccountException(AccountExceptionCode.CODE_MAX);
        }
        //取出实际的验证码
        String code = redisUtil.get(RedisKeyUtil.registerCodeKey(uf.getUserInfoTel()));

        String code1 = uf.getCode();
        if (code1 == null || code1.equals("")) {
            throw new AccountException(AccountExceptionCode.CODE_NOT_NULL);
        }
        if (!uf.getCode().equals(code)) {
            if (!redisUtil.exists(RedisKeyUtil.erroTotal(uf.getUserInfoTel()))) {
                redisUtil.set(RedisKeyUtil.erroTotal(uf.getUserInfoTel()), "1", 5 * 60);
            } else {
                redisUtil.incr(RedisKeyUtil.erroTotal(uf.getUserInfoTel()));
            }
            throw new AccountException(AccountExceptionCode.VERIFICATION_CODE_ERROR);
        }
        boolean b = Lock.tryLock(20, TimeUnit.SECONDS);

        if (b) {
            try {
                QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
                wrapper.eq("user_info_tel", uf.getUserInfoTel());
                UserAccount userInfo = userAccountMapper.selectOne(wrapper);
                if (userInfo == null) {
                    //删除发送的验证码
                    redisUtil.del1(RedisKeyUtil.registerCodeKey(uf.getUserInfoTel()));
                    throw new AccountException(AccountExceptionCode.PHONE_NOT_REGISTER);
                }
            }
            finally
            {
                Lock.unlock();
            }
        }
        else
        {
            throw new AccountException(AccountExceptionCode.SERVER_BUSY);
        }
        QueryWrapper<UserAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("user_info_tel", uf.getUserInfoTel());
        UserAccount userInfo = userAccountMapper.selectOne(wrapper);

        return BeanUtil.toBean(userInfo,UserLoginDto.class);
    }

    @Override
    public void send1(String userInfoTel) throws Exception {
        if (redisUtil.exists(RedisKeyUtil.sendRegisterCodeInMinute(userInfoTel))) {
            throw new AccountException(AccountExceptionCode.DONT_ALWAYS_BUSY);
        }
        String total = redisUtil.get(RedisKeyUtil.codeTotalInHour(userInfoTel));
        if (total != null && Integer.parseInt(total) >= 5) {
            throw new AccountException(AccountExceptionCode.TIMEOUT);
        }

        String code = smsUtil.send(userInfoTel);
//        验证码存储在 Redis 中，并设置过期时间为 5 分钟。
        redisUtil.set(RedisKeyUtil.registerCodeKey(userInfoTel), code, 5 * 60);
//        设置过期时间为 60 秒。
        redisUtil.set(RedisKeyUtil.sendRegisterCodeInMinute(userInfoTel), "0", 60);
        if (!redisUtil.exists(RedisKeyUtil.codeTotalInHour(userInfoTel))) {
            redisUtil.set(RedisKeyUtil.codeTotalInHour(userInfoTel), "1", 60 * 60);
        } else {
            redisUtil.incr(RedisKeyUtil.codeTotalInHour(userInfoTel));
        }
    }

    @Override
    public UserAccount updateUserState(Integer id) {
        QueryWrapper<Object> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",id);
        UserAccount userAccount = userAccountMapper.selectById(id);
        Integer userState = userAccount.getUserState();
        System.out.println("---------------------");
        System.out.println(userState);
        System.out.println("---------------------");
        if (userState!=0){
            userAccount.setUserState(0);
        }else {
            userAccount.setUserState(1);
        }
        userAccountMapper.updateById(userAccount);
        return userAccount;
    }

    @Override
    public void userupdatePassword(String oldPass, String newPass, String id) {
        UserAccount userAccount = userAccountMapper.selectById(id);
        //用户不存在
        if (userAccount==null){
            throw new AccountException(AccountExceptionCode.NO_USER);
        }
        //判断旧密码是否正确
        if (!userAccount.getUserPass().equals(oldPass)){
            throw  new AccountException(AccountExceptionCode.PASS_ERROR);
        }
        System.out.println("lpl");
        System.out.println(oldPass);
        System.out.println(newPass);
        System.out.println("lpl");
        if (oldPass.equals(newPass)){
            throw  new AccountException(AccountExceptionCode.PASS_NOT_SAME);
        }
        userAccount.setUserPass(newPass);
        userAccountMapper.updateById(userAccount);
    }
}
